﻿using CSASPNETBackgroundWorker;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Web.UI.WebControls;
using System.Xml.Linq;

public partial class Katalog_Schody : BasePage
{
    private static readonly string _localSources = "/Site/App_Code/Sources/";
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void Timer1_Tick(object sender, EventArgs e)
    {
        // Show the progress of current operation.
        BackgroundWorker worker = (BackgroundWorker)Session["worker"];
        if (worker != null)
        {
            // Display the progress of the operation.
            //ProgressText.Text = "Loading: " + worker.Progress + "%";

            Timer1.Enabled = worker.IsRunning;

            // Display the result when the operation completed.
            if (worker.Progress >= 100)
            {
                string resultPath = Server.MapPath(_localSources + "WorkerResult" + Session.SessionID);
                if (File.Exists(resultPath)) File.Delete(resultPath);
                string[] res = (string[])worker.Result;
                Trace.Warn(res[1]);
                Progress.CssClass = "animated-hide";
                LoadRatesFromDatabase();
            }
        }
        else
        {
            bool finish = false;
            string resultPath = Server.MapPath(_localSources + "WorkerResult" + Session.SessionID);
            if (!(finish = File.Exists(resultPath)))
            {
                resultPath = Server.MapPath(_localSources + "WorkerResult");
                finish = File.Exists(resultPath);
            }
            if (finish)
            {
                Timer1.Enabled = false;
                string[] res = File.ReadAllLines(resultPath);
                File.Delete(resultPath);
                Trace.Warn(res[1]);
                Progress.CssClass = "animated-hide";
                LoadRatesFromDatabase();
            }
        }
    }
    protected void Initializer_Tick(object sender, EventArgs e)
    {
        Initializer.Enabled = false;
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new BackgroundWorker.DoWorkEventHandler(worker_DoWork);
        worker.RunWorker(_localSources + "LastA.xml", "http://www.nbp.pl/kursy/xml/LastA.xml");

        // It needs Session Mode is "InProc"
        // to keep the Background Worker working.
        Session["worker"] = worker;
        
        // Enable the timer to update the status of the operation.
        Timer1.Enabled = true;
    }

    void worker_DoWork(ref int progress, ref object result, params object[] arguments)
    {
        string logStream = "Log:";
        string localFilePath = Server.MapPath(arguments[0].ToString());
        string fileUrl = arguments[1].ToString();

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(fileUrl);
        if (File.Exists(localFilePath + ".stats"))
        {
            string[] stats = File.ReadAllLines(localFilePath + ".stats");
            request.Headers[HttpRequestHeader.IfNoneMatch] = stats[0];
            request.IfModifiedSince = DateTime.Parse(stats[1]);
            progress += 20;
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                SaveSourceFile(localFilePath, response);
                logStream += "\nUpdated data successfully";
            }
            catch (System.Net.WebException ex)
            {
                if (ex.Response != null)
                {
                    using (HttpWebResponse response = ex.Response as HttpWebResponse)
                    {
                        if (response.StatusCode == HttpStatusCode.NotModified)
                             logStream += "\nUpdate not necessary";
                        else logStream += "\nUnexpected status code returned: " + response.StatusCode;
                    }
                }
                else logStream += "\nUnexpected problems while update";
            }
        }
        else
        {
            progress += 20;
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                // Not sure why it fails if no headers are set
                request.Headers[HttpRequestHeader.IfNoneMatch] = "000";
                request.IfModifiedSince = DateTime.Parse("1990-01-01");
                SaveSourceFile(localFilePath, response);
                logStream += "\nSaved new data successfully";
            }
            catch (Exception ex)
            {
                logStream += "\nUnexpected problems with first download:\n" + ex.Message;
            }
        }
        progress += 30;
        // The operation is completed.
        result = new string[] { "Operation is completed.", logStream };
        string id = "";
        try { id = Session.SessionID; } catch (Exception ex) { logStream += "\nNo SessionID availible"; }
        string prepath = _localSources + "WorkerResult" + id;
        string path = Server.MapPath(prepath);
        File.WriteAllLines(path, (string[])result);
    }

    private void SaveSourceFile(string localFilePath, HttpWebResponse response)
    {
        // Save last date of modification or eTag
        WebHeaderCollection headers = response.Headers;
        using (Stream stream = response.GetResponseStream())
        {
            DataClassesDataContext context = new DataClassesDataContext();
            XDocument xDoc = XDocument.Load(stream);
            foreach (var result in xDoc.Descendants("pozycja"))
            {
                KursyA record = new KursyA();
                record.nazwa_waluty = result.Element("nazwa_waluty").Value;
                record.przelicznik = int.Parse(result.Element("przelicznik").Value);
                record.kod_waluty = result.Element("kod_waluty").Value;
                record.kurs_sredni = result.Element("kurs_sredni").Value;
                KursyA oldRecord = context.KursyAs.FirstOrDefault(x => x.kod_waluty == record.kod_waluty);
                if (oldRecord != null)
                {
                    if (oldRecord.kurs_sredni != record.kurs_sredni) oldRecord.kurs_sredni = record.kurs_sredni;
                    else if (oldRecord.nazwa_waluty != record.nazwa_waluty) oldRecord.nazwa_waluty = record.nazwa_waluty;
                    else if (oldRecord.przelicznik != record.przelicznik) oldRecord.przelicznik = record.przelicznik;
                    else continue;
                }
                else context.KursyAs.InsertOnSubmit(record);
            }
            context.SubmitChanges();
        }
        File.WriteAllText(localFilePath + ".stats", String.Format("{0}\n{1}",
            headers[HttpResponseHeader.ETag],
            headers[HttpResponseHeader.LastModified]));
        response.Close();
    }

    private void LoadRatesFromDatabase()
    {
        Trace.Warn("Load Rates From Database");
        DataClassesDataContext context = new DataClassesDataContext();
        ExchangeRates.DataSource = context.GetTable<KursyA>();
        ExchangeRates.DataBind();
    }
    
    protected void gridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        ExchangeRates.PageIndex = e.NewPageIndex;
        DataClassesDataContext context = new DataClassesDataContext();
        ExchangeRates.DataSource = context.GetTable<KursyA>();
        ExchangeRates.DataBind();
    }
}